package cc.rengu.igas.share.core.service.trans;

import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.enums.RespCodeEnum;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.service.base.NoticeService;
import cc.rengu.igas.share.facade.request.UpacRefundResultNoticeRequest;
import cc.rengu.igas.share.facade.response.UpacRefundResultNoticeResponse;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.utility.util.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 银联全渠道退款结果通知服务
 * Created by fyp on 2020/5/6.
 */
public class UpacRefundResultNoticeService extends NoticeService implements TransCustomImpl {

    @Override
    protected Object bizBeforeCust() throws Exception {
        UpacRefundResultNoticeRequest upacRefundResultNoticeRequest = new UpacRefundResultNoticeRequest();
        ConvertUtil.convertOutput(upacRefundResultNoticeRequest);
        return upacRefundResultNoticeRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        UpacRefundResultNoticeRequest upacRefundResultNoticeRequest = (UpacRefundResultNoticeRequest) request;
        BizResponse bizResponse = new BizResponse();
        UpacRefundResultNoticeResponse refundResultNoticeResponse = new UpacRefundResultNoticeResponse();
        refundResultNoticeResponse.setHeader(upacRefundResultNoticeRequest.getHeader());
        String instId = upacRefundResultNoticeRequest.getHeader().getInstId();
        String orderId = upacRefundResultNoticeRequest.getOrderId();

        /* 根据订单号查询订单信息 */
        OrderService orderService = new OrderServiceImpl();
        OrderInfo refundOrderInfo = orderService.selectOrderInfoBySysSeqNum(instId, orderId);
        if (null == refundOrderInfo) {
            rglog.error("机构<{}>没有对应的银联订单号<{}>信息", upacRefundResultNoticeRequest.getHeader().getInstId(), upacRefundResultNoticeRequest.getOrderId());
            throw new BizException(RespCodeEnum.ORDER_NOT_EXIST.getRespCode(), RespCodeEnum.ORDER_NOT_EXIST.getRespDesc());
        }
        UserOrderInfo userOrderInfo = refundOrderInfo.getUserOrderInfo();
        List<MchntOrderInfo> mchntOrderInfoList = refundOrderInfo.getMchntOrderInfoList();
        Optional<PayOrderInfo> payOrderInfoOpt = refundOrderInfo.getPayOrderInfoList().stream().filter(item -> item.getMsgDstId().equals(ChannelEnum.UPAC.getChannelType())).findFirst();
        if (!payOrderInfoOpt.isPresent()) {
            rglog.error("机构<{}>没有对应的银联订单号<{}>信息", upacRefundResultNoticeRequest.getHeader().getInstId(), upacRefundResultNoticeRequest.getOrderId());
            throw new BizException(RespCodeEnum.ORDER_NOT_EXIST.getRespCode(), RespCodeEnum.ORDER_NOT_EXIST.getRespDesc());
        }
        PayOrderInfo payOrderInfo = payOrderInfoOpt.get();
        if (TransStatusEnum.TRANS_SUCC.getStatus().equals(payOrderInfo.getTransStatus()) &&
                (BizStatusEnum.FINISH.getStatus().equals(payOrderInfo.getBizStatus()) ||
                        BizStatusEnum.REFUND.getStatus().equals(payOrderInfo.getBizStatus()) ||
                        BizStatusEnum.PART_REFUND.getStatus().equals(payOrderInfo.getBizStatus()) ||
                        BizStatusEnum.CONFIRM.getStatus().equals(payOrderInfo.getBizStatus()))) {
            rglog.error("订单已成功，不处理直接返回结果");
            refundResultNoticeResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            refundResultNoticeResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            bizResponse.setResult(refundResultNoticeResponse);
            bizResponse.setRspSysId(AppParamConstant.IGAS);
            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            return bizResponse;
        }

        /* 根据响应结果修改交易状态 */
        String respCode = upacRefundResultNoticeRequest.getRespCode();
        rglog.info("无跳转通知中原退款交易的应答码:<{}>", respCode);
        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        if (!"00".equals(respCode)) {
            /*更新订单表状态为失败*/
            rglog.info("退款交易调用失败，退款订单更新状态为失败...");
            userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            userOrderInfo.setUpdateTime(currentDateTime);
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mchntOrderInfo.setUpdateTime(currentDateTime);
            }
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        } else {
            /*退款成功,更新当前退款订单状态*/
            rglog.info("退款交易调用成功,更新退款交易订单状态....");
            userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
            userOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            userOrderInfo.setUpdateTime(currentDateTime);
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                mchntOrderInfo.setUpdateTime(currentDateTime);
            }
            payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            payOrderInfo.setSettleDate(upacRefundResultNoticeRequest.getSettleDate());
            payOrderInfo.setRespCode(upacRefundResultNoticeRequest.getRespCode());
            payOrderInfo.setRespDesc(upacRefundResultNoticeRequest.getRespDesc());
        }
        payOrderInfo.setUpdateTime(currentDateTime);
        /* 更新订单信息 */
        if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
            rglog.error("更新支付订单状态失败");
            throw new BizException(RespCodeEnum.ORDER_UPDATE_ERROR.getRespCode(), RespCodeEnum.ORDER_UPDATE_ERROR.getRespDesc());
        }

        /* 获取原支付订单信息 */
        String origSysSeqNum = refundOrderInfo.getUserOrderInfo().getOrigSysSeqNum();
        OrderInfo origOrderInfo = orderService.selectOrderInfoBySysSeqNum(instId, origSysSeqNum);
        if (null == origOrderInfo) {
            rglog.info("根据原系统流水号<{}>获取原支付订单信息失败!", origSysSeqNum);
            throw new BizException(RespCodeEnum.ORDER_NOT_EXIST.getRespCode(), RespCodeEnum.ORDER_NOT_EXIST.getRespDesc());
        }
        GlobalTransUtil.setCacheValue(TransCacheConstant.ORIG_ORDER_INFO, origOrderInfo);

        //调用通道接口
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.TRANS_NOT_SUPPORT.getRespCode(), RespCodeEnum.TRANS_NOT_SUPPORT.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(upacRefundResultNoticeRequest, channelCallCfgList);
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, refundOrderInfo, channelCallCfg.getBizScene(), request);

        /* 组装应答报文 */
        bizResponse.setResult(refundResultNoticeResponse);
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        if (!"00".equals(respCode)) {
            bizResponse.setRespDesc(RespCodeEnum.TRANS_IN_PROGRESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_IN_PROGRESS.getRespDesc());
        } else {
            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            /* 更新商户累计退款限额 */
            MchntService mchntService = new MchntServiceImpl();
            mchntService.updateMchntTransLimit(mchntOrderInfoList);
            /* 更新原支付订单信息 */
            updateOrigPayOrderInfo(refundOrderInfo, origOrderInfo);
        }
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        UpacRefundResultNoticeResponse refundResultNoticeResponse = (UpacRefundResultNoticeResponse) bizResponse.getResult();
        ConvertUtil.convertInput(refundResultNoticeResponse);
    }

    /**
     * 更新原支付订单信息
     *
     * @param refundOrderInfo 退款订单信息
     * @param origOrderInfo   原支付订单信息
     * @throws Exception 异常
     */
    private void updateOrigPayOrderInfo(OrderInfo refundOrderInfo, OrderInfo origOrderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String totalRefundAmt = "0.00";
        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        UserOrderInfo origUserOrderInfo = origOrderInfo.getUserOrderInfo();
        List<MchntOrderInfo> origMchntOrderInfiList = origOrderInfo.getMchntOrderInfoList();
        Optional<PayOrderInfo> payOrderInfoOpt = origOrderInfo.getPayOrderInfoList().stream().filter(item -> item.getMsgDstId().equals(ChannelEnum.UPAC.getChannelType())).findFirst();
        if (!payOrderInfoOpt.isPresent()) {
            rglog.info("根据原系统流水号<{}>获取原支付订单信息失败!", refundOrderInfo.getUserOrderInfo().getOrigSysSeqNum());
            throw new BizException(RespCodeEnum.ORDER_NOT_EXIST.getRespCode(), RespCodeEnum.ORDER_NOT_EXIST.getRespDesc());
        }
        PayOrderInfo origPayOrderInfo = payOrderInfoOpt.get();

        /*累计用户退款金额*/
        for (MchntOrderInfo mchntOrderInfo : origMchntOrderInfiList) {
            if (mchntOrderInfo.getRefundAmt() != null) {
                totalRefundAmt = AmountUtil.addition(mchntOrderInfo.getRefundAmt(), totalRefundAmt);
            }
        }
        totalRefundAmt = AmountUtil.addition(refundOrderInfo.getUserOrderInfo().getOrderAmt(), totalRefundAmt);
        rglog.debug("流程日志-累计用户退款金额:<{}>", totalRefundAmt);

        //判断用户是否全额退款
        rglog.info("用户订单金额:<{}>,累计退款金额:<{}>", origUserOrderInfo.getOrderAmt(), totalRefundAmt);
        if (AmountUtil.compare(origUserOrderInfo.getOrderAmt(), totalRefundAmt) == 0) {
            xmlTreeUtil.setXmlTreeStringValue("refundType", AppParamConstant.YES);
            origUserOrderInfo.setBizStatus(BizStatusEnum.REFUND.getStatus());
        } else {
            origUserOrderInfo.setBizStatus(BizStatusEnum.PART_REFUND.getStatus());
        }
        origUserOrderInfo.setUpdateTime(currentDateTime);

        //更新商户累计退款金额
        List<MchntOrderInfo> mchntOrderInfoList = new ArrayList<>();
        for (MchntOrderInfo mchntOrderInfoRefund : refundOrderInfo.getMchntOrderInfoList()) {
            List<MchntOrderInfo> mchntOrderInfos = origMchntOrderInfiList.stream().filter(item -> item.getMchntNo().equals(mchntOrderInfoRefund.getMchntNo())).collect(Collectors.toList());
            /*累计退款金额*/
            MchntOrderInfo mchntOrderInfo = mchntOrderInfos.get(0);
            mchntOrderInfo.setRefundAmt(AmountUtil.addition(mchntOrderInfo.getRefundAmt(), mchntOrderInfoRefund.getOrderAmt()));
            if (AmountUtil.compare(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getRefundAmt()) == 0) {
                mchntOrderInfo.setBizStatus(BizStatusEnum.REFUND.getStatus());
            } else {
                mchntOrderInfo.setBizStatus(BizStatusEnum.PART_REFUND.getStatus());
            }
            mchntOrderInfo.setRefundFee(AmountUtil.addition(mchntOrderInfo.getRefundFee(), mchntOrderInfoRefund.getMchntFee()));
            mchntOrderInfo.setUpdateTime(currentDateTime);
            mchntOrderInfoList.add(mchntOrderInfo);
        }
        origPayOrderInfo.setBizStatus(origUserOrderInfo.getBizStatus());
        origPayOrderInfo.setUpdateTime(currentDateTime);
        /*更新原支付订单业务状态为部分/全额退款、商户订单累计退款金额*/
        rglog.debug("流程日志-累计原订单信息的业务状态:<{}>", origUserOrderInfo.getBizStatus());
        OrderService orderService = new OrderServiceImpl();
        if (!orderService.updateOrderInfo(origUserOrderInfo, mchntOrderInfoList, origPayOrderInfo)) {
            rglog.error("更新商户累计退款金额失败");
            throw new BizException(RespCodeEnum.ORDER_UPDATE_ERROR.getRespCode(), RespCodeEnum.ORDER_UPDATE_ERROR.getRespDesc());
        }
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        /* 业务场景类型：00-原支付失败场景，01-原支付交易成功 */
        UpacRefundResultNoticeRequest upacRefundResultNoticeRequest = (UpacRefundResultNoticeRequest) request;
        Optional<ChannelCallCfg> channelCallCfgOpt;
        if (!RespCodeEnum.TRANS_SUCCESS.getRespCode().equals(upacRefundResultNoticeRequest.getRespCode())) {
            /* 原退款交易失败 */
            channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("00")).findFirst();
        } else {
            /* 原退款交易成功 */
            channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("01")).findFirst();
        }
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        OrderInfo origOrderInfo = (OrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_ORDER_INFO);
        if (null != origOrderInfo && ChannelEnum.MOMP.getChannelType().equals(channelCallCfg.getCallChannelId())) {
            MchntOrderInfo mchntOrderInfo = origOrderInfo.getMchntOrderInfoList().get(0);
            if (mchntOrderInfo.getMchntDiscountFee() != null &&
                    !mchntOrderInfo.getMchntDiscountFee().isEmpty() &&
                    AmountUtil.compare(mchntOrderInfo.getMchntDiscountFee(), "0.00") > 0) {
                /*非合并订单支付的全额退款也属于全订单退款，判断是否有有续费优惠*/
                return CheckResultEnum.PASSED;
            } else {
                return CheckResultEnum.NEXT;
            }
        } else {
            return CheckResultEnum.PASSED;
        }
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return null;
    }
}
